<?php
declare(strict_types=1);
/**
 * 商品购物车
 * @author chenshubo
 */

namespace App\Model\PssModel;
use App\Model\BaseModel\BasePssModel;
use App\Service\Code\Normal;
use Throwable;
use App\Service\OrderService\OrderQueryService\QueryGoodsMicService;
use Hyperf\DbConnection\Db;

class GoodsCart extends BasePssModel
{
    public $table = 'goods_cart';
    
    protected $casts = [
        'id' => 'string',
        'goods_id' => 'string',
        'spec_num' => 'string',
        'store_id' => 'string',
    ];
    
    /**
     * 加入购物车数据
     * @param array $param
     */
    public function addCart( $param = [] ) 
    {
        if( empty($param['body']) ) {
            return Normal::returnCode(Normal::FAIL,"except param body");
        }
        
        if( empty($param['binfo']) ) {
            return Normal::returnCode(Normal::FAIL,"except param binfo");
        }
        
        $orderItem  = $param['body']['goods_list'];
        $goodsInfo  = $param['body']['goodsInfo'];
        $specInfo   = current($orderItem);
        $bid        = $param['binfo']['bid'];
        $goodsInfo  = array_column($goodsInfo,null,'goods_id');
        
        if( empty($specInfo['store_id']) ) {
            return Normal::returnCode(Normal::FAIL,"except param goods_list.store_id");
        }
        
        if( empty($specInfo['batch_no']) ) {
            return Normal::returnCode(Normal::FAIL,"except param goods_list.batch_no");
        }
        
        if( empty($specInfo['spec_num']) ) {
            return Normal::returnCode(Normal::FAIL,"except param goods_list.spec_num");
        }
        
        /* if( empty($specInfo['price']) ) {
            return Normal::returnCode(Normal::FAIL,"except param goods_list.price");
        } */
        
        if( empty($specInfo['goods_num']) ) {
            return Normal::returnCode(Normal::FAIL,"except param goods_list.goods_num");
        }
        
        if( empty($specInfo['goods_id']) ) {
            return Normal::returnCode(Normal::FAIL,"except param goods_list.goods_id");
        }
        
        self::startTrans();
        
        //执行更新购物车状态
        try {
            foreach ($orderItem as $specInfo ) 
            {
                $goods_id  = $specInfo['goods_id'];
                $goods_num = $specInfo['goods_num'];
                $store_id  = $specInfo['store_id'];
                $batch_no  = $specInfo['batch_no'];
                $spec_num  = $specInfo['spec_num'];
                if( !isset($goodsInfo[$goods_id]) ) 
                {
                    return Normal::returnCode(Normal::FAIL,"商品【{$goods_id}】已下架");
                }
                
                $storeList = array_column($goodsInfo[$goods_id]['storeList'],null,'store_id');
                if( !isset($storeList[$store_id]) )
                {
                    return Normal::returnCode(Normal::FAIL,"仓库【{$store_id}】数据已下架");
                }
                
                $goods_batch_list = $storeList[$store_id]['goods_batch_list'];
                $goods_batch_list = array_column($goods_batch_list,null,'batch_no');
                if( !isset($goods_batch_list[$batch_no]) )
                {
                    return Normal::returnCode(Normal::FAIL,"商品【{$goods_id}】批次【{$batch_no}】已下架");
                }
                
                $specList = $goods_batch_list[$batch_no]['spec_list'];
                $specList = array_column($specList,null,'spec_num');
                if( !isset($specList[$spec_num]) )
                {
                    return Normal::returnCode(Normal::FAIL,"商品【{$goods_id}】批次【{$batch_no}】规格【{$spec_num}】已下架");
                }
                
                $price = $specList[$spec_num]['price'];
                $where = [
                    'bid'      => $bid,
                    'goods_id' => $goods_id,
                    'spec_num' => $spec_num,
                    'store_id' => $store_id,
                    'batch_no' => $batch_no,
                ];
                //如果是购物车加减
                $isExist = $this->info($where);
                if( !empty($isExist) ) 
                {
                    $condition = [
                        'bid'       => $bid,
                        'id'        => $isExist['id'],
                        'goods_num' => $isExist['goods_num'],
                        'goods_id'  => $isExist['goods_id'],
                        'spec_num'  => $isExist['spec_num'],
                        'store_id'  => $isExist['store_id'],
                        'batch_no'  => $isExist['batch_no'],
                    ];
                    $data = [
                        'price'     => $price,
                        'goods_num' => $goods_num,
                        'md'        => time()
                    ];
                    $res = $this->edit($condition,$data);
                } else {
                    
                    $insert = $where;
                    $insert['price']        = $price;
                    $insert['goods_num']    = $goods_num;
                    $insert['cd']           = time();
                    $res = $this->add($insert);
                }
                
                if( !$res ) {
                    self::rollback();
                    return Normal::returnCode(Normal::FAIL,"请求处理失败，请稍后再试");
                }
            }
            
            self::commit();
            return Normal::returnCode(Normal::SUC,"操作成功",[
                'totalCartGoods' => $this->where('bid',$bid)->count()
            ]);
        } catch ( Throwable $e ) {
            self::rollback();
            return Normal::returnCode(Normal::FAIL,"操作失败【{$e->getMessage()}】");
        }
    }
    
    /**
     * 删除接口
     */
    public function removeCartGoods( $param = [] ) 
    {
        $binfo = $param['binfo'];
        $body  = $param['body'];
        if( empty($body['cart_ids']) ) {
            return Normal::returnCode(Normal::FAIL,"except param cart_ids");
        }
        
        if( !is_array($body['cart_ids']) ) {
            return Normal::returnCode(Normal::FAIL,"cart_ids必须为数组[1,2]");
        }
        
        $res = $this->where('bid',$binfo['bid'])->whereIn('id',$body['cart_ids'])->delete();
        if( $res ) {
            return Normal::returnCode(Normal::SUC,"操作成功");
        }
        
        return Normal::returnCode(Normal::FAIL,"操作失败");
    }
    
    /**
     * 根据购物车id 计算选中商品购物价格
     */
    public function getCardGoodsPriceByCardIds( $param = [] )
    {
        $binfo = $param['binfo'];
        $body  = $param['body'];
        if( empty($body['card_ids']) ) {
            return Normal::returnCode(Normal::FAIL,"except param card_ids");
        }
        
        $card_ids = array_filter(array_unique($body['card_ids']));
        $select = [
            'goods_id',
            'spec_num',
            'price',
            'goods_num',
            'store_id',
            'batch_no'
        ];
        $resCartRow  = $this->select($select)->whereIn('id',$card_ids)->where('bid',$binfo['bid'])->get()->toArray();
        $total_money = 0;
        if( $resCartRow ) {
            //根据商品goods_id 获取商品实时价格并且参与计算
            $skuIds = array_values(array_unique(array_column($resCartRow, 'goods_id')));
            $queryParameters = [
                'body' => [
                    'skuIDS'        => $skuIds,
                    'limit'         => count($skuIds),
                    'order_goods'   => $resCartRow
                ],
                'binfo' => $binfo,
            ];
            $res = QueryGoodsMicService::instance()->getShopBestGoodsList($queryParameters);
            if( $res['code'] != Normal::SUC ) {
                return $res;
            }
            
            $micGoodsDataList = $res['data'];
            if( empty($micGoodsDataList) ) {
                return Normal::returnCode(Normal::SUC,"微服务商品数据获取为空，请检查商品服务接口是否正常！");
            }
            
            $goodsListMap = array_column($micGoodsDataList,null,'goods_id');
            foreach ($resCartRow as $item  )
            {
                $goods_id = $item['goods_id'];
                $spec_num = $item['spec_num'];
                $batch_no = $item['batch_no'];
                $store_id = $item['store_id'];
            
                //真实价格
                $price = $this->getRealGoodsPrice($goodsListMap,$item);
                if( !$price ) {
                    continue;
                }
            
                $price_total = bcmul((string)$price, (string)$item['goods_num'],2);
                $total_money = bcadd((string)$total_money, (string)$price_total,2);
            }
        }
        
        return Normal::returnCode(Normal::SUC,"获取成功",[
            "goodsCount"        => count(array_column($resCartRow,null,'goods_id')),
            'goodsTotalMoney'   => number_format((float)$total_money,2)
        ]); 
    }
    
    /**
     * 获取购物车列表数据
     */
    public function getCartGoodsList( $param = [] )
    {
        $binfo = $param['binfo'];
        $select = [
            'id as cart_id',
            Db::raw("CONCAT('',goods_id) as goods_id"),
            'spec_num',
            'price',
            'goods_num',
            'store_id',
            'batch_no'
        ];
        $resCartRow     = $this->rows(['bid' => $binfo['bid'],'is_down'=>0],$select);
        $cartGoodsList  = [];
        if( !empty($resCartRow) )
        {
            //根据商品goods_id 获取商品实时价格并且参与计算
            $skuIds = array_values(array_unique(array_column($resCartRow, 'goods_id')));
            $queryParameters = [
                'body' => [
                    'skuIDS'        => $skuIds,
                    'limit'         => count($skuIds),
                    'order_goods'   => $resCartRow
                ],
                'binfo' => $binfo,
            ];
            $res = QueryGoodsMicService::instance()->getShopBestGoodsList($queryParameters);
            if( $res['code'] != Normal::SUC ) {
                return $res;
            }
            
            $micGoodsDataList = $res['data'];
            if( empty($micGoodsDataList) ) {
                return Normal::returnCode(Normal::SUC,"微服务商品数据获取为空，请检查商品服务接口是否正常！",[
                    'cart_list' => []
                ]);
            }
            
            //组装购物车金额
            $goodsListMap = array_column($micGoodsDataList,null,'goods_id');
            $goodsTotalMoney = 0;
            foreach ($resCartRow as $key => & $goods ) 
            {
                if( !isset($goodsListMap[$goods['goods_id']]) ) 
                {
                    unset($resCartRow[$key]);
                    continue;
                }
                
                //真实价格
                $price = $this->getRealGoodsPrice($goodsListMap,$goods);
                if( !$price ) {
                    continue;
                }
    
                $currentGoods               = $goodsListMap[$goods['goods_id']];
                $goods['price']             = $price;
                $goods['goods_name']        = $currentGoods['goods_name'];
                $goods['goods_type']        = $currentGoods['goods_type'];
                $goods['goods_type_name']   = $currentGoods['goods_type_name'];
                $goods['image']             = $currentGoods['image'];
                $total_money                = bcmul((string)$goods['goods_num'], (string)$price,2);
                $goodsTotalMoney            = bcadd((string)$goodsTotalMoney,(string)$total_money,2);
                $goods['total']             = $total_money;
            }
            
            if( !empty($resCartRow) ) {
                rsort($resCartRow);
                if( isset($currentGoods['store_id']) ) {
                    $cartGoodsList[] = [
                        'store_id'      => $currentGoods['store_id'],
                        'store_name'    => current($currentGoods['storeList'])['store_name'],
                        'goods_list'    => $resCartRow,
                    ];
                }
            }
        }
        return Normal::returnCode(Normal::SUC,"获取成功",[
            'cart_list' => $cartGoodsList
        ]);
    }    
    
    /**
     * 获取真实价格
     * @param array $goodsMap
     * @param array $item
     */
    public function getRealGoodsPrice( $goodsListMap = []  , $item = [] )
    {
        $goods_id = $item['goods_id'];
        $spec_num = $item['spec_num'];
        $batch_no = $item['batch_no'];
        $store_id = $item['store_id'];
        
        if( !isset($goodsListMap[$goods_id]) ) {
            return false;
        }

        $goodsInfo = $goodsListMap[$goods_id];
        $storeList = array_column($goodsInfo['storeList'], null,'store_id');
        if( !isset($storeList[$store_id]) ) {
            return false;
        }
     
        $storeInfo = $storeList[$store_id];
        $batchList = array_column($storeInfo['goods_batch_list'], null,'batch_no');
        if( !isset($batchList[$batch_no]) ) {
            return false;
        }
        
        $specList = array_column($batchList[$batch_no]['spec_list'], null,'spec_num');
        if( !isset($specList[$spec_num]) ) {
            return false;
        }
        
        return $specList[$spec_num]['price'];
    }
        
    /**
     * 检查一般贸易、保税商品、海外直邮不能一起下单
     */
    public function checkoutOrderCartGoodsData( $param = [] ) 
    {
        if( empty($param['goods_list']) ) {
            return Normal::returnCode(Normal::FAIL,"goods_list不能为空");
        }
        
        $goods_list = $param['goods_list'];
        $storeList = array_unique(array_column($goods_list, 'store_id'));
        if( count($storeList) > 1 ) {
            return Normal::returnCode(Normal::FAIL,"不能跨仓下单");
        }
        
        $currentCart = current($goods_list);
        if( isset($currentCart['cart_id']) ) {
            $cart = array_unique(array_column($goods_list, 'goods_id'));
            if( count($cart) != count($goods_list) ) {
                return Normal::returnCode(Normal::FAIL,"同一仓内同一种商品不同批次或不同件装不能同时结算");
            }
        }
        
        $skuIds     = array_unique(array_column($goods_list, 'goods_id'));
        $goodsLists = $this->getCartGoodsBySkuIds($skuIds);
        $goodsTypes = array_unique(array_column($goodsLists, 'goods_type','goods_id'));
        $buyGoodsBuyMap = array_column($goods_list, 'goods_num','goods_id');
        
        //检查一般贸易、保税商品、海外直邮 
        if( count($goodsTypes) == 3 ) {
            return Normal::returnCode(Normal::FAIL,"一般贸易、保税商品、海外直邮商品不能同时下单");
        } else if( count($goodsTypes) == 2 ) {
            
            if( in_array(GoodsCommon::GOODS_TYPE_YBMY, $goodsTypes) && in_array(GoodsCommon::GOODS_TYPE_BSSP, $goodsTypes) ) { //一般贸易、保税商品
                return Normal::returnCode(Normal::FAIL,"一般贸易、保税商品不能同时下单");
            } else if( in_array(GoodsCommon::GOODS_TYPE_YBMY, $goodsTypes) && in_array(GoodsCommon::GOODS_TYPE_HWZY, $goodsTypes) ) { //一般贸易、海外直邮 
                return Normal::returnCode(Normal::FAIL,"一般贸易、海外直邮商品不能同时下单");
            } else  if( in_array(GoodsCommon::GOODS_TYPE_BSSP, $goodsTypes) && in_array(GoodsCommon::GOODS_TYPE_HWZY, $goodsTypes) ) {//保税商品、海外直邮 
                return Normal::returnCode(Normal::FAIL,"保税商品、海外直邮商品不能同时下单");
            }
        } else if(  count($goodsTypes) == 1 ) {
            $type = current($goodsTypes);
            $buyCount = current($buyGoodsBuyMap);
            if( $type == GoodsCommon::GOODS_TYPE_BSSP && $buyCount > 1 ) {
                return Normal::returnCode(Normal::FAIL,"保税商品下单数量不能超过1件");
            } else if( $type == GoodsCommon::GOODS_TYPE_HWZY && $buyCount > 1  ) {
                return Normal::returnCode(Normal::FAIL,"海外直邮商品下单数量不能超过1件");
            }
        }
        
        return Normal::returnCode(Normal::SUC,"校验通过");
    }
    
    /**
     * 加入购物车
     */
    public function addGoodsCart($param)
    {        
        $res = QueryGoodsMicService::instance()->checkBuyGoods($param);
        if( $res['code'] != Normal::SUC ) {
            return $res;
        }
        
        $param['body']['goodsInfo'] = $res['data']['goodsInfo'];
        $param['body']['goods_list'] = $res['data']['orderItem'];
        return $this->addCart($param);
    }
    
    /**
     * 购物车商品进行结算
     */
    public function cartGoodsOrder( $param = [] )
    {
        return QueryGoodsMicService::instance()->placeOrder($param);
    }
}